package com.ruoyi.dj.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.biz.BizModule;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.dj.domain.SpaceParamProduceParam;
import com.ruoyi.dj.domain.SpaceParamProduceVO;
import com.ruoyi.dj.service.ISpaceParamProduceService;
import com.ruoyi.system.domain.ResultSave;
import com.ruoyi.system.service.IResultSaveService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SpaceParamProduceServiceImpl implements ISpaceParamProduceService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private IResultSaveService resultSaveService;

    @Autowired
    private ISysDictDataService sysDictDataService;


    @Override
    public List<SpaceParamProduceVO> cal(SpaceParamProduceParam param) {

        List<SpaceParamProduceVO> resList = new ArrayList<>(param.getModels().size());
        String res = exec(param);
        JSONObject resObj = JSONUtil.parseObj(res);
        Set<String> types = resObj.keySet();
        //查询type的中文名字
        for (String type : types) {
            JSONObject jsonObject = resObj.getJSONObject(type);
            SpaceParamProduceVO vo = new SpaceParamProduceVO();
            Integer code = jsonObject.getInt("code");
            vo.setCode(code);
            String name = sysDictDataService.selectDictLabel("mult_cal_produce_models",type);
            vo.setModel(name);
            if (1 != code) {
                //异常直接跳过
                vo.setMsg(jsonObject.getStr("msg"));
            }else {
                //解析返回文件
                String filePath = jsonObject.getStr("outFile");
                try {
                    BufferedReader reader = new BufferedReader(new FileReader(filePath));
                    //首行是表头
                    String head = reader.readLine();
                    String[] headers = head.split("\\s+");
                    String line = "";
                    List lines = new ArrayList<>();
                    while (null != (line = reader.readLine())) {
                        //日期是一个空格 其余是多个
                        String[] split = line.split("\\t");
                        lines.add(split);
                    }
                    vo.setHeads(headers);
                    vo.setBody(lines);
                }catch (Exception e) {
                    log.error("制备解析报错",e);
                    vo.setMsg("系统异常");
                }
            }
            resList.add(vo);
        }
        return resList;
    }

    private String exec(SpaceParamProduceParam param) {

        //缓存
        String key = "produce:"+MD5.create().digestHex(param.toString());
        String cachRes = (String) redisTemplate.opsForValue().get(key);
        if (null == cachRes) {
            //调用脚本
            String script = PathUtil.codeModuleDir(BizModule.MODEL_CAL) + PathUtil.moduleDirs().getModelCal().get("produce");

            List<String> params = new ArrayList<>();
            params.add("python");
            params.add(script);
            //模型 逗号拼接
            String models = CollectionUtil.join(param.getModels(), ",");
            params.add(models);
            //开始时间 'yyyy-MM-dd HH:mm:ss'
            String stStr = DateUtil.format(param.getStartTime(), DatePattern.PURE_DATETIME_PATTERN);
            params.add( stStr);
            //结束时间 'yyyy-MM-dd HH:mm:ss'
            String edStr = DateUtil.format(param.getEndTime(), DatePattern.PURE_DATETIME_PATTERN);
            params.add(edStr);
            String cmd = CollectionUtil.join(params, " ");
            log.info("参数制备命令:{}", cmd);
            String res = RuntimeUtil.execForStr(cmd);
            log.info("参数制备命令结果:{}", res);
            redisTemplate.opsForValue().set(key,res,10, TimeUnit.MINUTES);
            cachRes = res;
        }
        return cachRes;
    }

    @Override
    public void save(SpaceParamProduceParam param) {
        String res = exec(param);
        JSONObject resObj = JSONUtil.parseObj(res);
        Set<String> types = resObj.keySet();
        List<String> list = new ArrayList<>();
        for (String type : types) {
            JSONObject jsonObject = resObj.getJSONObject(type);
            SpaceParamProduceVO vo = new SpaceParamProduceVO();
            Integer code = jsonObject.getInt("code");
            vo.setCode(code);
            vo.setModel(type);
            if (1 == code) {
                //异常直接跳过
                String filePath = jsonObject.getStr("outFile");
                list.add(filePath);
            }
        }

        ResultSave entity = ResultSave.builder()
                .params("")
                .module(ResultSaveModule.MODEL_CAL)
                .submodule(ResultSaveModule.MODEL_CAL_PARAM)
                .resultData(JSONUtil.toJsonStr(list))
                .startTime(DateUtil.format(param.getStartTime(),"yyyy-MM-dd"))
                .endTime(DateUtil.format(param.getEndTime(),"yyyy-MM-dd"))
                .createTime(new Date())
                .build();
        resultSaveService.resultSave(param,entity);

    }

    @Override
    public String download(SpaceParamProduceParam param) {
        List<File> resList = new ArrayList<>(param.getModels().size());
        String res = exec(param);
        JSONObject resObj = JSONUtil.parseObj(res);
        Set<String> types = resObj.keySet();
        for (String type : types) {
            JSONObject jsonObject = resObj.getJSONObject(type);
            SpaceParamProduceVO vo = new SpaceParamProduceVO();
            Integer code = jsonObject.getInt("code");
            vo.setCode(code);
            if (1 == code) {
                //返回文件
                String filePath = jsonObject.getStr("outFile");
                resList.add(new File(filePath));
            }
        }
        String path = RuoYiConfig.getDownloadPath() + DateUtil.format(new Date(), "yyyyMMddHHmmss")+".zip";
        File[] srcFiles = ArrayUtil.toArray(resList, File.class);
        ZipUtil.zip(new File(path), false, srcFiles);
        return path;
    }
}
